WebRTC 殴り書きメモ
NAT越え
Wiki
壁を越えろ!WebRTCでNAT/Firewallを越えて通信しよう
STUNだけで様子をみる。
TRUNはお金かかりそう
STUNではダメな場合は少なそうな気がする
対称型のNAT
対称型のFirewall
UDPポートが空いてない
UniP2P でもSTUNのみだった
STUNの規格
NAT あたりの知識も必要そう
NAT の Wiki:概要だけっぽい
STUN の Wiki STUNで解決できるNATの種類とかある。キーワードは拾えそう
WebRTCの裏側にあるNATの話
参考になるRFCとかの話も書いてある
NAT技術者にお勧めするRFCとドラフト
ICE
NAT越えの統一的な仕組みを提供する?
Wiki
概要としてわかりやすいスライドシェア
流れがわかりやすいスライド
RFC
WebRTC
W3C 仕様
MDN
Google のやつ
WebRTCの商用サービスまとめ|Twilio, SkyWay,agora.io など
WebRTC セキュリティ概説
WebRTCを使ってみよう!
WebRTC 入門
原文が良さそう。概要だけじゃなくて詳細を知るためのリンクが豊富そう
WebRTC コトハジメ
WebRTC connectivity
SDPのやりとり
統計情報
殴り書き
https://ja.wikipedia.org/wiki/UDPホールパンチング
Hamachi
Freenet
OpenAyame
Perfect Negotiation
WebRTCの整理
ピアの接続
方法
自分のアドレスなどの情報をまとめたSDPの作成
SDPのやりとりをするためのシグナリングサーバー
オファー/アンサーの交渉でSDPを確立させる(確立できない場合はどうなる?)
STUNなどでICE候補を収集して
シグナリングサーバーでやりとりする
受け取ったICE候補から、接続の試行などをして、最終的な接続先を決定する
上記の接続方法をICEと呼び、一般的なやり方の模様
データ通信
殴り書き
接続さえできれば、この辺は難しくなさそう
RTCDataChannel とか使う?
UDP上でやりとりするなら信頼性の担保が必要?RTCDataChannel が吸収してくれる?
所感
アウトラインは掴めてきたけど、厳密な部分がぼんやりしている。
実際にコードを書いてハッキリさせるか
RFCなどで厳密な定義を知るか
のどちらかが有効そう
どう手をつけるべきか
候補
WebRTCを使ってみよう!
古くて動くか心配
STUNサーバーはこれに出てくるものを使いたい
Google のやつ
Firebase を使うのが嫌だ
WebRTC samples
サンプルなので解説がないのがちょい辛そう
テキストのやり取り
基本的なピア接続
Peer connection using Perfect Negotiation
ICE candidate gathering from STUN/TURN servers
Do an ICE restart
Multiple peer connections at once
テキトウにQiitaで探す
まとめ
WebRTC samplesで基本的なものだけ動かしてみて、写経(動くコードを習得)
WebRTCを使ってみよう!(上記で動かないコードとかにも対応できるはず)
RTCPeerConnection
概要
ローカルコンピューターとリモートピア間のWebRTC接続を表します。
リモートピアに接続し、接続を維持および監視し、必要がなくなったら接続を閉じる方法を提供します。
icecandidateイベント
RTCPeerConnection.setLocalDescription() の呼び出しによって、RTCIceCandidateがローカルピアに追加されると、icecandidateイベントがRTCPeerConnectionに送信されます。
イベントハンドラは、候補をシグナリングチャネルを介してリモートピアに送信し、リモートピアが候補をリモート候補のセットに追加できるようにする必要があります。
onicecandidate
RTCPeerConnectionインスタンスでicecandidateイベントが発生したときに呼び出される関数を指定するEventHandlerです。
これは、ローカルICEエージェントがシグナリングサーバーを介して他のピアにメッセージを配信する必要がある場合に発生します。
これにより、ICEエージェントは、ブラウザ自体がシグナリングに使用されているテクノロジーに関する詳細を知る必要なしに、リモートピアとのネゴシエーションを実行できます。このメソッドを実装して、ICE候補をリモートピアに送信するために選択したメッセージングテクノロジーを使用します。
ondatachannel
RTCPeerConnection.ondatachannelプロパティは、RTCPeerConnectionでデータチャネルイベントが発生したときに呼び出される関数を指定するEventHandlerです。
このイベントは、createDataChannel()を呼び出すリモートピアによってRTCDataChannelが接続に追加されたときに送信されます。
このイベントが受信された時点で、それが示すRTCDataChannelはまだ実際には開いていない可能性があります。新しいRTCDataChannelで「open」イベントが発生するのを待ってから使用してください。
negotiationneeded イベント
シグナリングチャネルを介した接続のネゴシエーションが必要な場合、ネゴシエーションが必要なイベントがRTCPeerConnectionに送信されます。
これは、接続の初期セットアップ中と、通信環境の変更によって接続の再構成が必要になったときの両方で発生します。
iOS safari 未対応
createOffer
このメソッドは、リモートピアへの新しいWebRTC接続を開始する目的でSDPオファーの作成を開始します。
SDPオファーには、WebRTCセッションに既に接続されているMediaStreamTracks、コーデック、ブラウザーでサポートされているオプション、およびシグナリングチャネルを介して潜在的なピアに送信して要求する目的でICEエージェントによって既に収集されている候補に関する情報が含まれます。接続、または既存の接続の構成を更新します。
戻り値はPromiseであり、オファーが作成されると、新しく作成されたオファーを含むRTCSessionDescriptionオブジェクトが渡されます。
createAnswer
このメソッドは、WebRTC接続のオファー/アンサーネゴシエーション中にリモートピアから受信したオファーに対するSDPアンサーを作成します。
回答は返送されたPromiseに配信され、交渉プロセスを続行するためにオファーのソースに送信される必要があります。
setLocalDescription
このメソッドは、接続に関連付けられているローカルのSDPを変更します。
SDPは、メディア形式を含む、接続のローカルエンドのプロパティを指定します。
2つのピアが構成について合意するまでSDPが交換されるため、setLocalDescription() を呼び出して送信されたSDPはすぐには有効になりません。代わりに、ネゴシエーションが完了するまで、現在の接続構成はそのまま残ります。
ネゴシエーションが完了して初めて、合意された構成が有効になります。
(接続がすでに確立されているときに setLocalDescription() が呼び出された場合は、再ネゴシエーションが進行中であるこを意味します(ネットワークの状態の変化に適応するため)。)
(このメソッドは、単一のパラメーター(セッションの説明)を受け取り、説明が変更されると非同期で実行されるPrmiseを返します。 )
引数にセッションの説明を明示的に指定しない場合、WebRTCランタイムはそれを正しく処理しようとします。
シグナリング状態がstable、have-local-offer、またはhave-remote-pranswerのいずれかである場合、WebRTCランタイムは自動的に新しいオファーを作成し、それを新しいローカル記述として設定します。
それ以外の場合、setLocalDescription() はアンサーを作成し、それが新しいローカル記述になります。
setRemoteDescription
このメソッドは、指定されたセッションのSDPをリモートピアの現在のオファーまたはアンサーとして設定します。
SDPは、メディア形式を含む、接続のリモートエンドのプロパティを指定します。
このメソッドは、単一のパラメーター(セッションのSDP)を受け取り、SDPが変更されると非同期で実行されるPromiseを返します。
これは通常、シグナリングサーバーを介して別のピアからオファーまたはアンサーを受信した後に呼び出されます。
接続がすでに確立されているときにsetRemoteDescription()が呼び出された場合、それは再ネゴシエーションが進行中であることを意味することに注意してください(おそらくネットワーク条件の変化に適応するため)。
2つのピアが構成について合意するまでSDPが交換されるため、setRemoteDescription()を呼び出して送信されたSDPはすぐには有効になりません。代わりに、ネゴシエーションが完了するまで、現在の接続構成はそのまま残ります。そうして初めて、合意された構成が有効になります。
signalingState
stable:
進行中のオファーとアンサーの継続的な交換はありません。
これは、RTCPeerConnectionオブジェクトが新しいことを意味している可能性があります。
その場合、localDescriptionとremoteDescriptionの両方がnullになります。
また、ネゴシエーションが完了し、接続が確立されたことを意味する場合もあります。
have-local-offer
ローカルピアは RTCPeerConnection.setLocalDescription() を呼び出し、オファーを表すSDPを渡し(通常はRTCPeerConnection.createOffer() を呼び出すことによって作成されます)、オファーは正常に適用されました。
have-remote-offer
リモートピアはオファーを作成し、シグナリングサーバーを使用してローカルピアに配信しました。
ローカルピアは、RTCPeerConnection.setRemoteDescription() を呼び出してオファーをリモートディスクリプションとして設定しました。
have-local-pranswer
リモートピアによって送信されたオファーが適用され、応答が作成され(通常、RTCPeerConnection.createAnswer() を呼び出すことによって)、RTCPeerConnection.setLocalDescription() を呼び出すことによって適用されます。
この暫定回答では、サポートされているメディア形式などについて説明していますが、ICE候補の完全なセットが含まれていない場合があります。それ以上の候補者は後で別々に配達されます。
have-remote-pranswer
setLocalDescription() を呼び出すことによって以前に送信および確立されたオファーに応答して、暫定的な回答が受信され、正常に適用されました。
RTCDataChannel
概要
このチャネルを介して、あらゆる種類のデータを送信できます。
これは、画像、ファイル転送、テキストチャット、ゲーム更新パケットなどのバックチャネルコンテンツに役立ちます。
RTCPeerConnection.createDataChannel() によって作成できる
onopen
これは、データチャネルの基になるデータトランスポート(RTCDataChannelのメッセージが流れるリンク)が確立または再確立されたときに送信される単純なイベントです。
onclose
これは、データチャネルが閉じられたことを示す単純なイベントです。
onmessage
メッセージイベントがチャネルで発生したときに呼び出される関数を指定するEventHandlerを格納します。
他のピアからメッセージを受信したときに、このイベントはチャネルに送信されます。
RTCSessionDescription
RTCSessionDescriptionインターフェイスは、接続の一方の端(または潜在的な接続)とその構成方法を記述します。
各RTCSessionDescriptionは、オファー/アンサーネゴシエーションプロセスのどの部分を説明するかを示す説明タイプと、セッションのSDP記述子で構成されます。
2つのピア間の接続をネゴシエートするプロセスには、RTCSessionDescriptionオブジェクトの交換が含まれ、各Descriptionは、Descriptionの送信者がサポートする接続構成オプションの1つの組み合わせを提案します。
2つのピアが接続の設定について合意すると、ネゴシエーションは完了します。
ICEエージェント
ブラウザ側にある。
ICEのクライアントみたいな感じっぽい
ICEエージェント(単に「エージェント」と呼ばれることもあります)は、ICE候補交換に関与するプロトコル実装です。典型的な候補者の交換には2人のエージェントが関与しています。
よくわからない
疑問点
ICE候補の収集しきったことを通知してないのに、勝手に終了しているのが謎
テキストのやり取りの時に、コードでは null の AAddIceCandidate をしてないのに勝手にされていることが、コンソールから確認できる
おそらくRTCPeerConnectionの生成時にSTUNなどのアドレスを渡さなかったため、ローカルだけで候補を収集し終えたと判断されたのでは?
Perfect Negotiation
SDPを交換するための方法の一つ
両方同時にオファーを送ったらどうする?とか
negotiationneeded イベントが発火されるタイミングは?
2回ある。
初回と初回のオファーアンサーが終わった時、すぐに発火される
iOS Safari が未対応
negotiationneeded イベントがない
暗黙的なロールバックがない
restartICEもない
adapter.js でなんとかなるのかな -> ならないっぽい
ブラウザの未サポートが多いので、サンプルにあるような Perfect Negotiation はできない
未対応になっているものを、自前でする必要がある
2021 年に出た WebRTC 関連 RFC 一覧
https://www.rfc-editor.org/rfc/rfc8825.html
https://www.rfc-editor.org/rfc/rfc8831.html
https://www.rfc-editor.org/rfc/rfc8830.html